package typejump.objects;

import typejump.Settings;
import typejump.engine.CollisionProps;
import typejump.engine.GameAction;
import typejump.util.Mutil;

/**
 * Actor class which represents some kind of creature with health and stuff.
 * @author g
 *
 */
public class Actor extends Sprite {
	
	private double jumpspeed = 0;
	private String name = "";
	private String lname = "";
	private double maxhealth = 10;
	private double health = maxhealth;
	
	private double damageTimer = 0;
	private double damageInterval = 0;
	
	public double getJumpVelocity() {
		return jumpspeed;
	}
	
	public void setJumpHeight(double h) {
		this.jumpspeed = Mutil.getVoFor(-h, getGravity());
	}
	
	public Actor(String name) {
		this.name = name;
		this.lname = name.toLowerCase();
		canFall = true;
		physical = true;
		dynamic = true;
		moveable = true;
		setCollision(CollisionProps.T_NPC, CollisionProps.T_ITEM|CollisionProps.T_GEOM);
		
		setJumpHeight(Settings.getDouble(lname + ".jump"));
	}
	
	public void setDamageInterval(double time) {
		this.damageInterval = time;
	}
	
	public void setMaxHealth(double health) {
		if (health <= 1) health = 1;
		this.maxhealth = this.health = health;
	}
	
	public void setHealth(double health) {
		this.health = health;
	}
	
	public boolean damage(double damage) {
		if (damageTimer > 0) return false;
		if (damage <= 0) return false;
		health -= damage;
		damageTimer = damageInterval;
		return true;
	}
	public void heal(double health) {
		this.health = Math.min(this.health+health, this.maxhealth);
	}
	
	public double getHealth() {
		return health;
	}
	public double healthProportion() {
		return health / maxhealth;
	}
	
	public void die() {
		playAnimation("die", new GameAction() { 
			public void act(GameObject a, GameObject b) {
				a.remove();
			}
		});
	}
	
	/**
	 * Returns true if this was just squished
	 * @return
	 */
	private boolean checkSquishing() {
		boolean pu = vars().get("push up")    > 0;
		boolean pd = vars().get("push down")  > 0;
		boolean pl = vars().get("push left")  > 0;
		boolean pr = vars().get("push right") > 0;

		if (pu) vars().mod("push up",    -1);
		if (pd) vars().mod("push down",  -1);
		if (pl) vars().mod("push left",  -1);
		if (pr) vars().mod("push right", -1);

		return (pu & pd) || (pl & pr);
	}
	
	@Override
	public boolean paintEnabled() {
		if (damageTimer <= 0 || damageInterval <= 0)
			return true;
		
		// this much time elapses between flickers
		double flicker = 0.1; 
		
		boolean off = false;
		double val = 0;
		
		while ((val += flicker) < damageTimer)
			off = !off;
		return off;
	}
	
	public void update(double seconds) {
		super.update(seconds);
		
		if (checkSquishing()) {
			die();
		}
		
		if (health <= 0)
			die();
		
		if (damageTimer > 0)
			damageTimer -= seconds;

		// This code is required for the "jump" command to function.
		// I wish there was a more elegant way to reset jumps,
		// but I can't think of anything creative at the moment.
		if (isOnGround() && vy() >= groundedOn.vy()) {
			vars().set("jumps", 0);
		}
	}
}
